package com.yida.gwj.expend.handler;

import java.util.Optional;

import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.yida.common.core.exception.ServiceException;
import com.yida.gwj.common.domain.mq.MqSendResult;
import com.yida.gwj.common.handler.MqSendMessageHandler;
import com.yida.gwj.common.utils.GwjEnumUtils;
import com.yida.gwj.expend.config.MaintenanceFundsBusinessConfiguration;
import com.yida.gwj.expend.domain.GwjMaintenanceFundsBusiness;
import com.yida.gwj.expend.domain.message.MaintenanceFundsMqMessageBody;
import com.yida.gwj.expend.domain.message.PreAcceptSecondExamineInnerMessage;
import com.yida.gwj.expend.enums.BusinessStatusEnum;
import com.yida.gwj.expend.enums.MaintenanceFundsErrorEnum;
import com.yida.gwj.expend.service.IGwjMaintenanceFundsBusinessService;

import cn.hutool.json.JSONUtil;

/**
 * 二次提交MQ事务处理
 *
 * @author liangp
 * @date 2023/03/14
 * @link <a href="https://www.jianshu.com/p/09920b4a7267">RocketMQ--事务消息</a>
 *       <p>
 *       三种状态: COMMIT：提交事务，允许订阅方消费该消息。 ROLLBACK：回滚事务，消息将被丢弃不允许消费。 Unknow：暂时无法判断状态，等待固定时间以后消息队列RocketMQ版服务端向发送方进行消息回查。
 */
@Component
public class PreAcceptSecondExamineHalfListener implements TransactionListener {

    private final Logger log = LoggerFactory.getLogger(PreAcceptSecondExamineHalfListener.class);

    @Autowired
    private MqSendMessageHandler mqSendMessageHandler;
    @Autowired
    private MaintenanceFundsBusinessConfiguration maintenanceFundsBusinessConfiguration;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public LocalTransactionState executeLocalTransaction(Message message, Object arg) {
        log.info("[MQ][二次附件审核]半事务消息处理 -> [{}]", message);
        PreAcceptSecondExamineInnerMessage preAcceptSecondExamineInnerMessage = (PreAcceptSecondExamineInnerMessage)arg;
        String tag = maintenanceFundsBusinessConfiguration.tagProperties().getPreAcceptSecondExamineInner();
        MqSendResult mqSendResult = mqSendMessageHandler.syncSend(new MaintenanceFundsMqMessageBody() {
            {
                setJsonMsg(JSONUtil.toJsonStr(preAcceptSecondExamineInnerMessage));
                setServerIdentification(preAcceptSecondExamineInnerMessage.getMaintenanceFundsBusiness().getServerIdentification());
            }
        }, new MaintenanceFundsBusinessConfiguration.MaintenanceFundsBusinessSendRequest(tag, null));
        if (mqSendResult.isSuccess()) {
            Optional.ofNullable(((IGwjMaintenanceFundsBusinessService)AopContext.currentProxy()).updateGwjMaintenanceFundsBusinessInner(new GwjMaintenanceFundsBusiness() {
                {
                    setBizId(preAcceptSecondExamineInnerMessage.getMaintenanceFundsBusiness().getBizId());
                    setStatus(BusinessStatusEnum.APPROVED.getCode());
                }
            })).<ServiceException>orElseThrow(() -> {
                throw new ServiceException(GwjEnumUtils.getEnumConstantMsg(MaintenanceFundsErrorEnum.PRE_ACCEPT_SECOND_EXAMINE) + "公共维修资金业务GwjMaintenanceFundsBusiness更新失败");
            });
            return LocalTransactionState.COMMIT_MESSAGE;
        } else {
            log.error("[MQ][二次附件审核]半事务消息处理异常 -> [{}]", mqSendResult.getMessage());
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
        log.info("[MQ][二次附件审核]半事务[未知]消息处理 -> [{}]", messageExt);
        return LocalTransactionState.COMMIT_MESSAGE;
    }
}
